home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / nasm095s.zip / PREPROC.C < prev    next >
C/C++ Source or Header  |  1997-07-27  |  63KB  |  2,283 lines

  1. /* preproc.c   macro preprocessor for the Netwide Assembler
  2.  *
  3.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  4.  * Julian Hall. All rights reserved. The software is
  5.  * redistributable under the licence given in the file "Licence"
  6.  * distributed in the NASM archive.
  7.  *
  8.  * initial version 18/iii/97 by Simon Tatham
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <stddef.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16.  
  17. #include "nasm.h"
  18. #include "nasmlib.h"
  19.  
  20. typedef struct SMacro SMacro;
  21. typedef struct MMacro MMacro;
  22. typedef struct Context Context;
  23. typedef struct Token Token;
  24. typedef struct Line Line;
  25. typedef struct Include Include;
  26. typedef struct Cond Cond;
  27. typedef struct IncPath IncPath;
  28.  
  29. /*
  30.  * Store the definition of a single-line macro.
  31.  */
  32. struct SMacro {
  33.     SMacro *next;
  34.     char *name;
  35.     int casesense;
  36.     int nparam;
  37.     int in_progress;
  38.     Token *expansion;
  39. };
  40.  
  41. /*
  42.  * Store the definition of a multi-line macro.
  43.  */
  44. struct MMacro {
  45.     MMacro *next;
  46.     char *name;
  47.     int casesense;
  48.     int nparam_min, nparam_max;
  49.     int plus;                   /* is the last parameter greedy? */
  50.     int nolist;                   /* is this macro listing-inhibited? */
  51.     int in_progress;
  52.     Token **defaults, *dlist;
  53.     Line *expansion;
  54. };
  55.  
  56. /*
  57.  * The context stack is composed of a linked list of these.
  58.  */
  59. struct Context {
  60.     Context *next;
  61.     SMacro *localmac;
  62.     char *name;
  63.     unsigned long number;
  64. };
  65.  
  66. /*
  67.  * This is the internal form which we break input lines up into.
  68.  * Typically stored in linked lists.
  69.  *
  70.  * TOK_PS_OTHER is a token type used internally within
  71.  * expand_smacro(), to denote a token which has already been
  72.  * checked for being a potential macro, but may still be a context-
  73.  * local label.
  74.  *
  75.  * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
  76.  * necessarily used as-is, but is intended to denote the number of
  77.  * the substituted parameter. So in the definition
  78.  *
  79.  *     %define a(x,y) ( (x) & ~(y) )
  80.  * 
  81.  * the token representing `x' will have its type changed to
  82.  * TOK_SMAC_PARAM, but the one representing `y' will be
  83.  * TOK_SMAC_PARAM+1.
  84.  *
  85.  * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
  86.  * which doesn't need quotes around it. Used in the pre-include
  87.  * mechanism as an alternative to trying to find a sensible type of
  88.  * quote to use on the filename we were passed.
  89.  */
  90. struct Token {
  91.     Token *next;
  92.     char *text;
  93.     SMacro *mac;               /* associated macro for TOK_MAC_END */
  94.     int type;
  95. };
  96. enum {
  97.     TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
  98.     TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_PS_OTHER, TOK_SMAC_PARAM,
  99.     TOK_INTERNAL_STRING
  100. };
  101.  
  102. /*
  103.  * Multi-line macro definitions are stored as a linked list of
  104.  * these, which is essentially a container to allow several linked
  105.  * lists of Tokens.
  106.  * 
  107.  * Note that in this module, linked lists are treated as stacks
  108.  * wherever possible. For this reason, Lines are _pushed_ on to the
  109.  * `expansion' field in MMacro structures, so that the linked list,
  110.  * if walked, would give the macro lines in reverse order; this
  111.  * means that we can walk the list when expanding a macro, and thus
  112.  * push the lines on to the `expansion' field in _istk_ in reverse
  113.  * order (so that when popped back off they are in the right
  114.  * order). It may seem cockeyed, and it relies on my design having
  115.  * an even number of steps in, but it works...
  116.  *
  117.  * Some of these structures, rather than being actual lines, are
  118.  * markers delimiting the end of the expansion of a given macro.
  119.  * This is for use in the cycle-tracking code. Such structures have
  120.  * `finishes' non-NULL, and `first' NULL. All others have
  121.  * `finishes' NULL, but `first' may still be NULL if the line is
  122.  * blank.
  123.  */
  124. struct Line {
  125.     Line *next;
  126.     MMacro *finishes;
  127.     Token *first;
  128. };
  129.  
  130. /*
  131.  * To handle an arbitrary level of file inclusion, we maintain a
  132.  * stack (ie linked list) of these things.
  133.  */
  134. struct Include {
  135.     Include *next;
  136.     FILE *fp;
  137.     Cond *conds;
  138.     Line *expansion;
  139.     char *fname;
  140.     int lineno, lineinc;
  141. };
  142.  
  143. /*
  144.  * Include search path. This is simply a list of strings which get
  145.  * prepended, in turn, to the name of an include file, in an
  146.  * attempt to find the file if it's not in the current directory.
  147.  */
  148. struct IncPath {
  149.     IncPath *next;
  150.     char *path;
  151. };
  152.  
  153. /*
  154.  * Conditional assembly: we maintain a separate stack of these for
  155.  * each level of file inclusion. (The only reason we keep the
  156.  * stacks separate is to ensure that a stray `%endif' in a file
  157.  * included from within the true branch of a `%if' won't terminate
  158.  * it and cause confusion: instead, rightly, it'll cause an error.)
  159.  */
  160. struct Cond {
  161.     Cond *next;
  162.     int state;
  163. };
  164. enum {
  165.     /*
  166.      * These states are for use just after %if or %elif: IF_TRUE
  167.      * means the condition has evaluated to truth so we are
  168.      * currently emitting, whereas IF_FALSE means we are not
  169.      * currently emitting but will start doing so if a %else comes
  170.      * up. In these states, all directives are admissible: %elif,
  171.      * %else and %endif. (And of course %if.)
  172.      */
  173.     COND_IF_TRUE, COND_IF_FALSE,
  174.     /*
  175.      * These states come up after a %else: ELSE_TRUE means we're
  176.      * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
  177.      * any %elif or %else will cause an error.
  178.      */
  179.     COND_ELSE_TRUE, COND_ELSE_FALSE,
  180.     /*
  181.      * This state means that we're not emitting now, and also that
  182.      * nothing until %endif will be emitted at all. It's for use in
  183.      * two circumstances: (i) when we've had our moment of emission
  184.      * and have now started seeing %elifs, and (ii) when the
  185.      * condition construct in question is contained within a
  186.      * non-emitting branch of a larger condition construct.
  187.      */
  188.     COND_NEVER
  189. };
  190. #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
  191.  
  192. /*
  193.  * Condition codes. Note that we use c_ prefix not C_ because C_ is
  194.  * used in nasm.h for the "real" condition codes. At _this_ level,
  195.  * we treat CXZ and ECXZ as condition codes, albeit non-invertible
  196.  * ones, so we need a different enum...
  197.  */
  198. static char *conditions[] = {
  199.     "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
  200.     "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
  201.     "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
  202. };
  203. enum {
  204.     c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
  205.     c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
  206.     c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
  207. };
  208. static int inverse_ccs[] = {
  209.     c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
  210.     c_A, c_AE, c_B, c_BE, c_C, c_E, c_G, c_GE, c_L, c_LE, c_O, c_P, c_S,
  211.     c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
  212. };
  213.  
  214. static Context *cstk;
  215. static Include *istk;
  216. static IncPath *ipath = NULL;
  217.  
  218. static efunc error;
  219.  
  220. static unsigned long unique;           /* unique identifier numbers */
  221.  
  222. static char *linesync, *outline;
  223.  
  224. static Line *predef = NULL;
  225.  
  226. static ListGen *list;
  227.  
  228. /*
  229.  * The number of hash values we use for the macro lookup tables.
  230.  */
  231. #define NHASH 31
  232.  
  233. /*
  234.  * The current set of multi-line macros we have defined.
  235.  */
  236. static MMacro *mmacros[NHASH];
  237.  
  238. /*
  239.  * The current set of single-line macros we have defined.
  240.  */
  241. static SMacro *smacros[NHASH];
  242.  
  243. /*
  244.  * The multi-line macro we are currently defining, if any.
  245.  */
  246. static MMacro *defining;
  247.  
  248. /*
  249.  * The number of macro parameters to allocate space for at a time.
  250.  */
  251. #define PARAM_DELTA 16
  252.  
  253. /*
  254.  * The standard macro set: defined as `static char *stdmac[]'. Also
  255.  * gives our position in the macro set, when we're processing it.
  256.  */
  257. #include "macros.c"
  258. static char **stdmacpos;
  259.  
  260. /*
  261.  * The pre-preprocessing stage... This function translates line
  262.  * number indications as they emerge from GNU cpp (`# lineno "file"
  263.  * flags') into NASM preprocessor line number indications (`%line
  264.  * lineno file').
  265.  */
  266. static char *prepreproc(char *line) {
  267.     int lineno, fnlen;
  268.     char *fname, *oldline;
  269.  
  270.     if (line[0] == '#' && line[1] == ' ') {
  271.     oldline = line;
  272.     fname = oldline+2;
  273.     lineno = atoi(fname);
  274.     fname += strspn(fname, "0123456789 ");
  275.     if (*fname == '"')
  276.         fname++;
  277.     fnlen = strcspn(fname, "\"");
  278.     line = nasm_malloc(20+fnlen);
  279.     sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
  280.     nasm_free (oldline);
  281.     }
  282.     return line;
  283. }
  284.  
  285. /*
  286.  * The hash function for macro lookups. Note that due to some
  287.  * macros having case-insensitive names, the hash function must be
  288.  * invariant under case changes. We implement this by applying a
  289.  * perfectly normal hash function to the uppercase of the string.
  290.  */
  291. static int hash(char *s) {
  292.     /*
  293.      * Powers of three, mod 31.
  294.      */
  295.     static const int multipliers[] = {
  296.     1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
  297.     30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
  298.     };
  299.     int h = 0;
  300.     int i = 0;
  301.  
  302.     while (*s) {
  303.     h += multipliers[i] * (unsigned char) (toupper(*s));
  304.     s++;
  305.     if (++i >= sizeof(multipliers)/sizeof(*multipliers))
  306.         i = 0;
  307.     }
  308.     h %= NHASH;
  309.     return h;
  310. }
  311.  
  312. /*
  313.  * Free a linked list of tokens.
  314.  */
  315. static void free_tlist (Token *list) {
  316.     Token *t;
  317.     while (list) {
  318.     t = list;
  319.     list = list->next;
  320.     nasm_free (t->text);
  321.     nasm_free (t);
  322.     }
  323. }
  324.  
  325. /*
  326.  * Free a linked list of lines.
  327.  */
  328. static void free_llist (Line *list) {
  329.     Line *l;
  330.     while (list) {
  331.     l = list;
  332.     list = list->next;
  333.     free_tlist (l->first);
  334.     nasm_free (l);
  335.     }
  336. }
  337.  
  338. /*
  339.  * Pop the context stack.
  340.  */
  341. static void ctx_pop (void) {
  342.     Context *c = cstk;
  343.     SMacro *smac, *s;
  344.  
  345.     cstk = cstk->next;
  346.     smac = c->localmac;
  347.     while (smac) {
  348.     s = smac;
  349.     smac = smac->next;
  350.     nasm_free (s->name);
  351.     free_tlist (s->expansion);
  352.     nasm_free (s);
  353.     }
  354.     nasm_free (c->name);
  355.     nasm_free (c);
  356. }
  357.  
  358. /*
  359.  * Generate a line synchronisation comment, to ensure the assembler
  360.  * knows which source file the current output has really come from.
  361.  */
  362. static void line_sync (void) {
  363.     char text[80];
  364.     sprintf(text, "%%line %d+%d %s",
  365.         (istk->expansion ? istk->lineno - istk->lineinc : istk->lineno),
  366.         (istk->expansion ? 0 : istk->lineinc), istk->fname);
  367.     if (linesync)
  368.     free (linesync);
  369.     linesync = nasm_strdup(text);
  370. }
  371.  
  372. #define BUF_DELTA 512
  373. /*
  374.  * Read a line from the top file in istk, handling multiple CR/LFs
  375.  * at the end of the line read, and handling spurious ^Zs. Will
  376.  * return lines from the standard macro set if this has not already
  377.  * been done.
  378.  */
  379. static char *read_line (void) {
  380.     char *buffer, *p, *q;
  381.     int bufsize;
  382.  
  383.     if (stdmacpos) {
  384.     if (*stdmacpos) {
  385.         char *ret = nasm_strdup(*stdmacpos++);
  386.         /*
  387.          * Nasty hack: here we push the contents of `predef' on
  388.          * to the top-level expansion stack, since this is the
  389.          * most convenient way to implement the pre-include and
  390.          * pre-define features.
  391.          */
  392.         if (!*stdmacpos) {
  393.         Line *pd, *l;
  394.         Token *head, **tail, *t, *tt;
  395.  
  396.         for (pd = predef; pd; pd = pd->next) {
  397.             head = NULL;
  398.             tail = &head;
  399.             for (t = pd->first; t; t = t->next) {
  400.             tt = *tail = nasm_malloc(sizeof(Token));
  401.             tt->next = NULL;
  402.             tail = &tt->next;
  403.             tt->type = t->type;
  404.             tt->text = nasm_strdup(t->text);
  405.             tt->mac = t->mac;   /* always NULL here, in fact */
  406.             }
  407.             l = nasm_malloc(sizeof(Line));
  408.             l->next = istk->expansion;
  409.             l->first = head;
  410.             l->finishes = FALSE;
  411.             istk->expansion = l;
  412.         }
  413.         }
  414.         return ret;
  415.     } else {
  416.         stdmacpos = NULL;
  417.         line_sync();
  418.     }
  419.     }
  420.  
  421.     bufsize = BUF_DELTA;
  422.     buffer = nasm_malloc(BUF_DELTA);
  423.     p = buffer;
  424.     while (1) {
  425.     q = fgets(p, bufsize-(p-buffer), istk->fp);
  426.     if (!q)
  427.         break;
  428.     p += strlen(p);
  429.     if (p > buffer && p[-1] == '\n') {
  430.         istk->lineno += istk->lineinc;
  431.         break;
  432.     }
  433.     if (p-buffer > bufsize-10) {
  434.         bufsize += BUF_DELTA;
  435.         buffer = nasm_realloc(buffer, bufsize);
  436.     }
  437.     }
  438.  
  439.     if (!q && p == buffer) {
  440.     nasm_free (buffer);
  441.     return NULL;
  442.     }
  443.  
  444.     /*
  445.      * Play safe: remove CRs as well as LFs, if any of either are
  446.      * present at the end of the line.
  447.      */
  448.     while (p > buffer && (p[-1] == '\n' || p[-1] == '\r'))
  449.     *--p = '\0';
  450.  
  451.     /*
  452.      * Handle spurious ^Z, which may be inserted into source files
  453.      * by some file transfer utilities.
  454.      */
  455.     buffer[strcspn(buffer, "\032")] = '\0';
  456.  
  457.     list->line (LIST_READ, buffer);
  458.  
  459.     return buffer;
  460. }
  461.  
  462. /*
  463.  * Tokenise a line of text. This is a very simple process since we
  464.  * don't need to parse the value out of e.g. numeric tokens: we
  465.  * simply split one string into many.
  466.  */
  467. static Token *tokenise (char *line) {
  468.     char *p = line;
  469.     int type;
  470.     Token *list = NULL;
  471.     Token *t, **tail = &list;
  472.  
  473.     while (*line) {
  474.     p = line;
  475.     if (*p == '%' &&
  476.         (p[1] == '{' || p[1] == '!' || (p[1] == '%' && isidchar(p[2])) ||
  477.          p[1] == '$' || p[1] == '+' || p[1] == '-' || isidchar(p[1]))) {
  478.         type = TOK_PREPROC_ID;
  479.         p++;
  480.         if (*p == '{') {
  481.         p++;
  482.         while (*p && *p != '}') {
  483.             p[-1] = *p;
  484.             p++;
  485.         }
  486.         p[-1] = '\0';
  487.         if (*p) p++;
  488.         } else {
  489.         if (*p == '!' || *p == '%' || *p == '$' ||
  490.             *p == '+' || *p == '-') p++;
  491.         while (*p && isidchar(*p))
  492.             p++;
  493.         }
  494.     } else if (isidstart(*p)) {
  495.         type = TOK_ID;
  496.         p++;
  497.         while (*p && isidchar(*p))
  498.         p++;
  499.     } else if (*p == '\'' || *p == '"') {
  500.         /*
  501.          * A string token.
  502.          */
  503.         char c = *p;
  504.         p++;
  505.         type = TOK_STRING;
  506.         while (*p && *p != c)
  507.         p++;
  508.         if (*p) p++;
  509.     } else if (isnumstart(*p)) {
  510.         /*
  511.          * A number token.
  512.          */
  513.         type = TOK_NUMBER;
  514.         p++;
  515.         while (*p && isnumchar(*p))
  516.         p++;
  517.     } else if (isspace(*p)) {
  518.         type = TOK_WHITESPACE;
  519.         p++;
  520.         while (*p && isspace(*p))
  521.         p++;
  522.         /*
  523.          * Whitespace just before end-of-line is discarded by
  524.          * pretending it's a comment; whitespace just before a
  525.          * comment gets lumped into the comment.
  526.          */
  527.         if (!*p || *p == ';') {
  528.         type = TOK_COMMENT;
  529.         while (*p) p++;
  530.         }
  531.     } else if (*p == ';') {
  532.         type = TOK_COMMENT;
  533.         while (*p) p++;
  534.     } else {
  535.         /*
  536.          * Anything else is an operator of some kind; with the
  537.          * exceptions of >>, <<, // and %%, all operator tokens
  538.          * are single-character.
  539.          */
  540.         char c = *p++;
  541.         type = TOK_OTHER;
  542.         if ( (c == '>' || c == '<' || c == '/' || c == '%') && *p == c)
  543.         p++;
  544.     }
  545.     if (type != TOK_COMMENT) {
  546.         *tail = t = nasm_malloc (sizeof(Token));
  547.         tail = &t->next;
  548.         t->next = NULL;
  549.         t->type = type;
  550.         t->text = nasm_malloc(1+p-line);
  551.         strncpy(t->text, line, p-line);
  552.         t->text[p-line] = '\0';
  553.     }
  554.     line = p;
  555.     }
  556.  
  557.     return list;
  558. }
  559.  
  560. /*
  561.  * Convert a line of tokens back into text.
  562.  */
  563. static char *detoken (Token *tlist) {
  564.     Token *t;
  565.     int len;
  566.     char *line, *p;
  567.  
  568.     len = 0;
  569.     for (t = tlist; t; t = t->next) {
  570.     if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
  571.         char *p = getenv(t->text+2);
  572.         nasm_free (t->text);
  573.         if (p)
  574.         t->text = nasm_strdup(p);
  575.         else
  576.         t->text = NULL;
  577.     }
  578.     if (t->text)
  579.         len += strlen(t->text);
  580.     }
  581.     p = line = nasm_malloc(len+1);
  582.     for (t = tlist; t; t = t->next) {
  583.     if (t->text) {
  584.         strcpy (p, t->text);
  585.         p += strlen(p);
  586.     }
  587.     }
  588.     *p = '\0';
  589.     return line;
  590. }
  591.  
  592. /*
  593.  * Return the Context structure associated with a %$ token. Return
  594.  * NULL, having _already_ reported an error condition, if the
  595.  * context stack isn't deep enough for the supplied number of $
  596.  * signs.
  597.  */
  598. static Context *get_ctx (char *name) {
  599.     Context *ctx;
  600.     int i;
  601.  
  602.     if (!cstk) {
  603.     error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is empty", name);
  604.     return NULL;
  605.     }
  606.  
  607.     i = 1;
  608.     ctx = cstk;
  609.     while (name[i+1] == '$') {
  610.     i++;
  611.     ctx = ctx->next;
  612.     if (!ctx) {
  613.         error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is only"
  614.            " %d level%s deep", name, i-1, (i==2 ? "" : "s"));
  615.         return NULL;
  616.     }
  617.     }
  618.     return ctx;
  619. }
  620.  
  621. /*
  622.  * Compare a string to the name of an existing macro; this is a
  623.  * simple wrapper which calls either strcmp or nasm_stricmp
  624.  * depending on the value of the `casesense' parameter.
  625.  */
  626. static int mstrcmp(char *p, char *q, int casesense) {
  627.     return casesense ? strcmp(p,q) : nasm_stricmp(p,q);
  628. }
  629.  
  630. /*
  631.  * Open an include file. This routine must always return a valid
  632.  * file pointer if it returns - it's responsible for throwing an
  633.  * ERR_FATAL and bombing out completely if not. It should also try
  634.  * the include path one by one until it finds the file or reaches
  635.  * the end of the path.
  636.  */
  637. static FILE *inc_fopen(char *file) {
  638.     FILE *fp;
  639.     char *prefix = "", *combine;
  640.     IncPath *ip = ipath;
  641.     int len = strlen(file);
  642.  
  643.     do {
  644.     combine = nasm_malloc(strlen(prefix)+len+1);
  645.     strcpy(combine, prefix);
  646.     strcat(combine, file);
  647.     fp = fopen(combine, "r");
  648.     nasm_free (combine);
  649.     if (fp)
  650.         return fp;
  651.     prefix = ip ? ip->path : NULL;
  652.     if (ip)
  653.         ip = ip->next;
  654.     } while (prefix);
  655.  
  656.     error (ERR_FATAL|ERR_OFFBY1,
  657.        "unable to open include file `%s'", file);
  658.     return NULL;               /* never reached - placate compilers */
  659. }
  660.  
  661. /*
  662.  * Determine if we should warn on defining a single-line macro of
  663.  * name `name', with `nparam' parameters. If nparam is 0, will
  664.  * return TRUE if _any_ single-line macro of that name is defined.
  665.  * Otherwise, will return TRUE if a single-line macro with either
  666.  * `nparam' or no parameters is defined.
  667.  *
  668.  * If a macro with precisely the right number of parameters is
  669.  * defined, the address of the definition structure will be
  670.  * returned in `defn'; otherwise NULL will be returned. If `defn'
  671.  * is NULL, no action will be taken regarding its contents, and no
  672.  * error will occur.
  673.  *
  674.  * Note that this is also called with nparam zero to resolve
  675.  * `ifdef'.
  676.  */
  677. static int smacro_defined (char *name, int nparam, SMacro **defn) {
  678.     SMacro *m;
  679.     Context *ctx;
  680.     char *p;
  681.  
  682.     if (name[0] == '%' && name[1] == '$') {
  683.     ctx = get_ctx (name);
  684.     if (!ctx)
  685.         return FALSE;           /* got to return _something_ */
  686.     m = ctx->localmac;
  687.     p = name+1;
  688.     p += strspn(p, "$");
  689.     } else {
  690.     m = smacros[hash(name)];
  691.     p = name;
  692.     }
  693.  
  694.     while (m) {
  695.     if (!mstrcmp(m->name, p, m->casesense) &&
  696.         (nparam == 0 || m->nparam == 0 || nparam == m->nparam)) {
  697.         if (defn) {
  698.         if (nparam == m->nparam)
  699.             *defn = m;
  700.         else
  701.             *defn = NULL;
  702.         }
  703.         return TRUE;
  704.     }
  705.     m = m->next;
  706.     }
  707.     return FALSE;
  708. }
  709.  
  710. /*
  711.  * Count and mark off the parameters in a multi-line macro call.
  712.  * This is called both from within the multi-line macro expansion
  713.  * code, and also to mark off the default parameters when provided
  714.  * in a %macro definition line.
  715.  */
  716. static void count_mmac_params (Token *t, int *nparam, Token ***params) {
  717.     int paramsize, brace;
  718.  
  719.     *nparam = paramsize = 0;
  720.     *params = NULL;
  721.     while (t) {
  722.     if (*nparam >= paramsize) {
  723.         paramsize += PARAM_DELTA;
  724.         *params = nasm_realloc(*params, sizeof(**params) * paramsize);
  725.     }
  726.     if (t && t->type == TOK_WHITESPACE)
  727.         t = t->next;
  728.     brace = FALSE;
  729.     if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
  730.         brace = TRUE;
  731.     (*params)[(*nparam)++] = t;
  732.     while (t && (t->type != TOK_OTHER ||
  733.              strcmp(t->text, brace ? "}" : ",")))
  734.         t = t->next;
  735.     if (t) {               /* got a comma/brace */
  736.         t = t->next;
  737.         if (brace) {
  738.         /*
  739.          * Now we've found the closing brace, look further
  740.          * for the comma.
  741.          */
  742.         if (t && t->type == TOK_WHITESPACE)
  743.             t = t->next;
  744.         if (t && (t->type != TOK_OTHER || strcmp(t->text, ","))) {
  745.             error (ERR_NONFATAL|ERR_OFFBY1,
  746.                "braces do not enclose all of macro parameter");
  747.             while (t && (t->type != TOK_OTHER ||
  748.                  strcmp(t->text, ",")))
  749.             t = t->next;
  750.         }
  751.         if (t)
  752.             t = t->next;           /* eat the comma */
  753.         }
  754.     }
  755.     else                   /* got EOL */
  756.         break;
  757.     }
  758. }
  759.  
  760. /*
  761.  * Find out if a line contains a preprocessor directive, and deal
  762.  * with it if so.
  763.  * 
  764.  * If a directive _is_ found, the line will never be de-tokenised
  765.  * as is, so we have carte blanche to fiddle with it and adjust
  766.  * token values.
  767.  *
  768.  * Return values go like this:
  769.  * 
  770.  * bit 0 is set if a directive was found
  771.  * bit 1 is set if a blank line should be emitted
  772.  * bit 2 is set if a re-sync line number comment should be emitted
  773.  *
  774.  * (bits 1 and 2 are mutually exclusive in that the rest of the
  775.  * preprocessor doesn't guarantee to be able to handle the case in
  776.  * which both are set)
  777.  */
  778. static int do_directive (Token *tline) {
  779.     static char *directives[] = {
  780.     "%clear", "%define", "%elifctx", "%elifdef", "%elifnctx",
  781.     "%elifndef", "%else", "%endif", "%endm", "%endmacro", "%error",
  782.     "%idefine", "%ifctx", "%ifdef", "%ifnctx", "%ifndef", "%imacro",
  783.     "%include", "%line", "%macro", "%pop", "%push", "%repl"
  784.     };
  785.     enum {
  786.     PP_CLEAR, PP_DEFINE, PP_ELIFCTX, PP_ELIFDEF, PP_ELIFNCTX,
  787.     PP_ELIFNDEF, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO, PP_ERROR,
  788.     PP_IDEFINE, PP_IFCTX, PP_IFDEF, PP_IFNCTX, PP_IFNDEF, PP_IMACRO,
  789.     PP_INCLUDE, PP_LINE, PP_MACRO, PP_POP, PP_PUSH, PP_REPL
  790.     };
  791.     int i, j, k, m, nparam;
  792.     char *p, *mname;
  793.     Include *inc;
  794.     Context *ctx;
  795.     Cond *cond;
  796.     SMacro *smac, **smhead;
  797.     MMacro *mmac;
  798.     Token *t, *tt, *param_start, *macro_start, *last;
  799.  
  800.     if (tline && tline->type == TOK_WHITESPACE)
  801.     tline = tline->next;
  802.     if (!tline || tline->type != TOK_PREPROC_ID ||
  803.     (tline->text[1]=='%' || tline->text[1]=='$' || tline->text[1]=='!'))
  804.     return 0;
  805.  
  806.     i = -1;
  807.     j = sizeof(directives)/sizeof(*directives);
  808.     while (j-i > 1) {
  809.     k = (j+i) / 2;
  810.     m = nasm_stricmp(tline->text, directives[k]);
  811.     if (m == 0) {
  812.         i = k;
  813.         j = -2;
  814.         break;
  815.     } else if (m < 0) {
  816.         j = k;
  817.     } else
  818.         i = k;
  819.     }
  820.  
  821.     /*
  822.      * If we're in a non-emitting branch of a condition construct,
  823.      * we should ignore all directives except for condition
  824.      * directives.
  825.      */
  826.     if (istk->conds && !emitting(istk->conds->state) &&
  827.     i != PP_IFCTX && i != PP_IFDEF && i != PP_IFNCTX && i != PP_IFNDEF &&
  828.     i!=PP_ELIFCTX && i!=PP_ELIFDEF && i!=PP_ELIFNCTX && i!=PP_ELIFNDEF &&
  829.     i != PP_ELSE && i != PP_ENDIF)
  830.     return 0;
  831.  
  832.     /*
  833.      * If we're defining a macro, we should ignore all directives
  834.      * except for %macro/%imacro (which generate an error) and
  835.      * %endm/%endmacro.
  836.      */
  837.     if (defining && i != PP_MACRO && i != PP_IMACRO &&
  838.     i != PP_ENDMACRO && i != PP_ENDM)
  839.     return 0;
  840.  
  841.     if (j != -2) {
  842.     error(ERR_NONFATAL|ERR_OFFBY1, "unknown preprocessor directive `%s'",
  843.           tline->text);
  844.     return 0;               /* didn't get it */
  845.     }
  846.  
  847.     switch (i) {
  848.  
  849.       case PP_CLEAR:
  850.     if (tline->next)
  851.         error(ERR_WARNING|ERR_OFFBY1,
  852.           "trailing garbage after `%%clear' ignored");
  853.     for (j=0; j<NHASH; j++) {
  854.         while (mmacros[j]) {
  855.         MMacro *m = mmacros[j];
  856.         mmacros[j] = mmacros[j]->next;
  857.         nasm_free (m->name);
  858.         free_tlist (m->dlist);
  859.         free_llist (m->expansion);
  860.         nasm_free (m);
  861.         }
  862.         while (smacros[j]) {
  863.         SMacro *s = smacros[j];
  864.         smacros[j] = smacros[j]->next;
  865.         nasm_free (s->name);
  866.         free_tlist (s->expansion);
  867.         nasm_free (s);
  868.         }
  869.     }
  870.     return 3;
  871.  
  872.       case PP_INCLUDE:
  873.     tline = tline->next;
  874.     if (tline && tline->type == TOK_WHITESPACE)
  875.         tline = tline->next;
  876.     if (!tline || (tline->type != TOK_STRING &&
  877.                tline->type != TOK_INTERNAL_STRING)) {
  878.         error(ERR_NONFATAL|ERR_OFFBY1, "`%%include' expects a file name");
  879.         return 3;               /* but we did _something_ */
  880.     }
  881.     if (tline->next)
  882.         error(ERR_WARNING|ERR_OFFBY1,
  883.           "trailing garbage after `%%include' ignored");
  884.     if (tline->type != TOK_INTERNAL_STRING) {
  885.         p = tline->text+1;           /* point past the quote to the name */
  886.         p[strlen(p)-1] = '\0';     /* remove the trailing quote */
  887.     } else
  888.         p = tline->text;           /* internal_string is easier */
  889.     inc = nasm_malloc(sizeof(Include));
  890.     inc->next = istk;
  891.     inc->conds = NULL;
  892.     inc->fp = inc_fopen(p);
  893.     inc->fname = nasm_strdup(p);
  894.     inc->lineno = inc->lineinc = 1;
  895.     inc->expansion = NULL;
  896.     istk = inc;
  897.     list->uplevel (LIST_INCLUDE);
  898.     return 5;
  899.  
  900.       case PP_PUSH:
  901.     tline = tline->next;
  902.     if (tline && tline->type == TOK_WHITESPACE)
  903.         tline = tline->next;
  904.     if (!tline || tline->type != TOK_ID) {
  905.         error(ERR_NONFATAL|ERR_OFFBY1,
  906.           "`%%push' expects a context identifier");
  907.         return 3;               /* but we did _something_ */
  908.     }
  909.     if (tline->next)
  910.         error(ERR_WARNING|ERR_OFFBY1,
  911.           "trailing garbage after `%%push' ignored");
  912.     ctx = nasm_malloc(sizeof(Context));
  913.     ctx->next = cstk;
  914.     ctx->localmac = NULL;
  915.     ctx->name = nasm_strdup(tline->text);
  916.     ctx->number = unique++;
  917.     cstk = ctx;
  918.     break;
  919.  
  920.       case PP_REPL:
  921.     tline = tline->next;
  922.     if (tline && tline->type == TOK_WHITESPACE)
  923.         tline = tline->next;
  924.     if (!tline || tline->type != TOK_ID) {
  925.         error(ERR_NONFATAL|ERR_OFFBY1,
  926.           "`%%repl' expects a context identifier");
  927.         return 3;               /* but we did _something_ */
  928.     }
  929.     if (tline->next)
  930.         error(ERR_WARNING|ERR_OFFBY1,
  931.           "trailing garbage after `%%repl' ignored");
  932.     if (!cstk)
  933.         error(ERR_NONFATAL|ERR_OFFBY1,
  934.           "`%%repl': context stack is empty");
  935.     else {
  936.         nasm_free (cstk->name);
  937.         cstk->name = nasm_strdup(tline->text);
  938.     }
  939.     break;
  940.  
  941.       case PP_POP:
  942.     if (tline->next)
  943.         error(ERR_WARNING|ERR_OFFBY1,
  944.           "trailing garbage after `%%pop' ignored");
  945.     if (!cstk)
  946.         error(ERR_NONFATAL|ERR_OFFBY1,
  947.           "`%%pop': context stack is already empty");
  948.     else
  949.         ctx_pop();
  950.     break;
  951.  
  952.       case PP_ERROR:
  953.     tline = tline->next;
  954.     if (tline && tline->type == TOK_WHITESPACE)
  955.         tline = tline->next;
  956.     if (!tline || tline->type != TOK_STRING) {
  957.         error(ERR_NONFATAL|ERR_OFFBY1,
  958.           "`%%error' expects an error string");
  959.         return 3;               /* but we did _something_ */
  960.     }
  961.     if (tline->next)
  962.         error(ERR_WARNING|ERR_OFFBY1,
  963.           "trailing garbage after `%%error' ignored");
  964.     p = tline->text+1;           /* point past the quote to the name */
  965.     p[strlen(p)-1] = '\0';           /* remove the trailing quote */
  966.     error(ERR_NONFATAL|ERR_OFFBY1, "user error: %s", p);
  967.     break;
  968.  
  969.       case PP_IFCTX:
  970.       case PP_IFNCTX:
  971.     tline = tline->next;
  972.     if (istk->conds && !emitting(istk->conds->state))
  973.         j = COND_NEVER;
  974.     else {
  975.         j = FALSE;               /* have we matched yet? */
  976.         if (!cstk)
  977.         error(ERR_FATAL|ERR_OFFBY1,
  978.               "`%%if%sctx': context stack is empty",
  979.               (i==PP_IFNCTX ? "n" : ""));
  980.         else while (tline) {
  981.         if (tline->type == TOK_WHITESPACE)
  982.             tline = tline->next;
  983.         if (!tline || tline->type != TOK_ID) {
  984.             error(ERR_NONFATAL|ERR_OFFBY1,
  985.               "`%%ifctx' expects context identifiers");
  986.             return 3;           /* but we did _something_ */
  987.         }
  988.         if (!nasm_stricmp(tline->text, cstk->name))
  989.             j = TRUE;
  990.         tline = tline->next;
  991.         }
  992.         if (i == PP_IFNCTX)
  993.         j = !j;
  994.         j = (j ? COND_IF_TRUE : COND_IF_FALSE);
  995.     }
  996.     cond = nasm_malloc(sizeof(Cond));
  997.     cond->next = istk->conds;
  998.     cond->state = j;
  999.     istk->conds = cond;
  1000.     return 1;
  1001.  
  1002.       case PP_ELIFCTX:
  1003.       case PP_ELIFNCTX:
  1004.     tline = tline->next;
  1005.     if (!istk->conds)
  1006.         error(ERR_FATAL|ERR_OFFBY1, "`%%elif%sctx': no matching `%%if'",
  1007.           (i==PP_ELIFNCTX ? "n" : ""));
  1008.     if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
  1009.         istk->conds->state = COND_NEVER;
  1010.     else {
  1011.         j = FALSE;               /* have we matched yet? */
  1012.         if (!cstk)
  1013.         error(ERR_FATAL|ERR_OFFBY1,
  1014.               "`%%elif%sctx': context stack is empty",
  1015.               (i==PP_ELIFNCTX ? "n" : ""));
  1016.         else while (tline) {
  1017.         if (tline->type == TOK_WHITESPACE)
  1018.             tline = tline->next;
  1019.         if (!tline || tline->type != TOK_ID) {
  1020.             error(ERR_NONFATAL|ERR_OFFBY1,
  1021.               "`%%elif%sctx' expects context identifiers",
  1022.               (i==PP_ELIFNCTX ? "n" : ""));
  1023.             return 3;           /* but we did _something_ */
  1024.         }
  1025.         if (!nasm_stricmp(tline->text, cstk->name))
  1026.             j = TRUE;
  1027.         tline = tline->next;
  1028.         }
  1029.         if (i == PP_ELIFNCTX)
  1030.         j = !j;
  1031.         istk->conds->state = (j ? COND_IF_TRUE : COND_IF_FALSE);
  1032.     }
  1033.     return 1;
  1034.  
  1035.       case PP_IFDEF:
  1036.       case PP_IFNDEF:
  1037.     tline = tline->next;
  1038.     if (istk->conds && !emitting(istk->conds->state))
  1039.         j = COND_NEVER;
  1040.     else {
  1041.         j = FALSE;               /* have we matched yet? */
  1042.         while (tline) {
  1043.         if (tline->type == TOK_WHITESPACE)
  1044.             tline = tline->next;
  1045.         if (!tline || (tline->type != TOK_ID &&
  1046.                    (tline->type != TOK_PREPROC_ID ||
  1047.                 tline->text[1] != '$'))) {
  1048.             error(ERR_NONFATAL|ERR_OFFBY1,
  1049.               "`%%if%sdef' expects macro identifiers",
  1050.               (i==PP_ELIFNDEF ? "n" : ""));
  1051.             return 3;           /* but we did _something_ */
  1052.         }
  1053.         if (smacro_defined(tline->text, 0, NULL))
  1054.             j = TRUE;
  1055.         tline = tline->next;
  1056.         }
  1057.         if (i == PP_IFNDEF)
  1058.         j = !j;
  1059.         j = (j ? COND_IF_TRUE : COND_IF_FALSE);
  1060.     }
  1061.     cond = nasm_malloc(sizeof(Cond));
  1062.     cond->next = istk->conds;
  1063.     cond->state = j;
  1064.     istk->conds = cond;
  1065.     return 1;
  1066.  
  1067.       case PP_ELIFDEF:
  1068.       case PP_ELIFNDEF:
  1069.     tline = tline->next;
  1070.     if (!istk->conds)
  1071.         error(ERR_FATAL|ERR_OFFBY1, "`%%elif%sctx': no matching `%%if'",
  1072.           (i==PP_ELIFNCTX ? "n" : ""));
  1073.     if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
  1074.         istk->conds->state = COND_NEVER;
  1075.     else {
  1076.         j = FALSE;               /* have we matched yet? */
  1077.         while (tline) {
  1078.         if (tline->type == TOK_WHITESPACE)
  1079.             tline = tline->next;
  1080.         if (!tline || (tline->type != TOK_ID &&
  1081.                    (tline->type != TOK_PREPROC_ID ||
  1082.                 tline->text[1] != '$'))) {
  1083.             error(ERR_NONFATAL|ERR_OFFBY1,
  1084.               "`%%elif%sdef' expects macro identifiers",
  1085.               (i==PP_ELIFNDEF ? "n" : ""));
  1086.             return 3;           /* but we did _something_ */
  1087.         }
  1088.         if (smacro_defined(tline->text, 0, NULL))
  1089.             j = TRUE;
  1090.         tline = tline->next;
  1091.         }
  1092.         if (i == PP_ELIFNDEF)
  1093.         j = !j;
  1094.         istk->conds->state = (j ? COND_IF_TRUE : COND_IF_FALSE);
  1095.     }
  1096.     return 1;
  1097.  
  1098.       case PP_ELSE:
  1099.     if (tline->next)
  1100.         error(ERR_WARNING|ERR_OFFBY1,
  1101.           "trailing garbage after `%%else' ignored");
  1102.     if (!istk->conds)
  1103.         error(ERR_FATAL|ERR_OFFBY1,
  1104.           "`%%else': no matching `%%if'");
  1105.     if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
  1106.         istk->conds->state = COND_ELSE_FALSE;
  1107.     else
  1108.         istk->conds->state = COND_ELSE_TRUE;
  1109.     return 1;
  1110.  
  1111.       case PP_ENDIF:
  1112.     if (tline->next)
  1113.         error(ERR_WARNING|ERR_OFFBY1,
  1114.           "trailing garbage after `%%endif' ignored");
  1115.     if (!istk->conds)
  1116.         error(ERR_FATAL|ERR_OFFBY1,
  1117.           "`%%endif': no matching `%%if'");
  1118.     cond = istk->conds;
  1119.     istk->conds = cond->next;
  1120.     nasm_free (cond);
  1121.     return 5;
  1122.  
  1123.       case PP_MACRO:
  1124.       case PP_IMACRO:
  1125.     if (defining)
  1126.         error (ERR_FATAL|ERR_OFFBY1,
  1127.            "`%%%smacro': already defining a macro",
  1128.            (i == PP_IMACRO ? "i" : ""));
  1129.     tline = tline->next;
  1130.     if (tline && tline->type == TOK_WHITESPACE)
  1131.         tline = tline->next;
  1132.     if (!tline || tline->type != TOK_ID) {
  1133.         error (ERR_NONFATAL|ERR_OFFBY1,
  1134.            "`%%%smacro' expects a macro name",
  1135.            (i == PP_IMACRO ? "i" : ""));
  1136.         return 3;
  1137.     }
  1138.     defining = nasm_malloc(sizeof(MMacro));
  1139.     defining->name = nasm_strdup(tline->text);
  1140.     defining->casesense = (i == PP_MACRO);
  1141.     defining->plus = FALSE;
  1142.     defining->nolist = FALSE;
  1143.     defining->in_progress = FALSE;
  1144.     tline = tline->next;
  1145.     if (tline && tline->type == TOK_WHITESPACE)
  1146.         tline = tline->next;
  1147.     if (!tline || tline->type != TOK_NUMBER) {
  1148.         error (ERR_NONFATAL|ERR_OFFBY1,
  1149.            "`%%%smacro' expects a parameter count",
  1150.            (i == PP_IMACRO ? "i" : ""));
  1151.         defining->nparam_min = defining->nparam_max = 0;
  1152.     } else {
  1153.         defining->nparam_min = defining->nparam_max =
  1154.         readnum(tline->text, &j);
  1155.         if (j)
  1156.         error (ERR_NONFATAL|ERR_OFFBY1,
  1157.                "unable to parse parameter count `%s'", tline->text);
  1158.     }
  1159.     if (tline && tline->next && tline->next->type == TOK_OTHER &&
  1160.         !strcmp(tline->next->text, "-")) {
  1161.         tline = tline->next->next;
  1162.         if (!tline || tline->type != TOK_NUMBER)
  1163.         error (ERR_NONFATAL|ERR_OFFBY1,
  1164.                "`%%%smacro' expects a parameter count after `-'",
  1165.                (i == PP_IMACRO ? "i" : ""));
  1166.         else {
  1167.         defining->nparam_max = readnum(tline->text, &j);
  1168.         if (j)
  1169.             error (ERR_NONFATAL|ERR_OFFBY1,
  1170.                "unable to parse parameter count `%s'",
  1171.                tline->text);
  1172.         if (defining->nparam_min > defining->nparam_max)
  1173.             error (ERR_NONFATAL|ERR_OFFBY1,
  1174.                "minimum parameter count exceeds maximum");
  1175.         }
  1176.     }
  1177.     if (tline && tline->next && tline->next->type == TOK_OTHER &&
  1178.         !strcmp(tline->next->text, "+")) {
  1179.         tline = tline->next;
  1180.         defining->plus = TRUE;
  1181.     }
  1182.     if (tline && tline->next && tline->next->type == TOK_ID &&
  1183.         !nasm_stricmp(tline->next->text, ".nolist")) {
  1184.         tline = tline->next;
  1185.         defining->nolist = TRUE;
  1186.     }
  1187.     mmac = mmacros[hash(defining->name)];
  1188.     while (mmac) {
  1189.         if (!strcmp(mmac->name, defining->name) &&
  1190.         (mmac->nparam_min<=defining->nparam_max || defining->plus) &&
  1191.         (defining->nparam_min<=mmac->nparam_max || mmac->plus)) {
  1192.         error (ERR_WARNING|ERR_OFFBY1,
  1193.                "redefining multi-line macro `%s'", defining->name);
  1194.         break;
  1195.         }
  1196.         mmac = mmac->next;
  1197.     }
  1198.     /*
  1199.      * Handle default parameters.
  1200.      */
  1201.     if (tline && tline->next) {
  1202.         int np, want_np;
  1203.  
  1204.         defining->dlist = tline->next;
  1205.         tline->next = NULL;
  1206.         count_mmac_params (defining->dlist, &np, &defining->defaults);
  1207.         want_np = defining->nparam_max - defining->nparam_min;
  1208.         defining->defaults = nasm_realloc (defining->defaults,
  1209.                            want_np*sizeof(Token *));
  1210.         while (np < want_np)
  1211.         defining->defaults[np++] = NULL;
  1212.     } else {
  1213.         defining->dlist = NULL;
  1214.         defining->defaults = NULL;
  1215.     }
  1216.     defining->expansion = NULL;
  1217.     return 1;
  1218.  
  1219.       case PP_ENDM:
  1220.       case PP_ENDMACRO:
  1221.     if (!defining) {
  1222.         error (ERR_NONFATAL|ERR_OFFBY1, "`%s': not defining a macro",
  1223.            tline->text);
  1224.         return 3;
  1225.     }
  1226.     k = hash(defining->name);
  1227.     defining->next = mmacros[k];
  1228.     mmacros[k] = defining;
  1229.     defining = NULL;
  1230.     return 5;
  1231.  
  1232.       case PP_DEFINE:
  1233.       case PP_IDEFINE:
  1234.     tline = tline->next;
  1235.     if (tline && tline->type == TOK_WHITESPACE)
  1236.         tline = tline->next;
  1237.     if (!tline || (tline->type != TOK_ID &&
  1238.                (tline->type != TOK_PREPROC_ID ||
  1239.             tline->text[1] != '$'))) {
  1240.         error (ERR_NONFATAL|ERR_OFFBY1,
  1241.            "`%%%sdefine' expects a macro identifier",
  1242.            (i == PP_IDEFINE ? "i" : ""));
  1243.         return 3;
  1244.     }
  1245.     mname = tline->text;
  1246.     if (tline->type == TOK_ID) {
  1247.         p = tline->text;
  1248.         smhead = &smacros[hash(mname)];
  1249.     } else {
  1250.         ctx = get_ctx (tline->text);
  1251.         if (ctx == NULL)
  1252.         return 3;
  1253.         else {
  1254.         p = tline->text+1;
  1255.         p += strspn(p, "$");
  1256.         smhead = &ctx->localmac;
  1257.         }
  1258.     }
  1259.     last = tline;
  1260.     param_start = tline = tline->next;
  1261.     nparam = 0;
  1262.     if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "(")) {
  1263.         /*
  1264.          * This macro has parameters.
  1265.          */
  1266.  
  1267.         tline = tline->next;
  1268.         while (1) {
  1269.         if (tline && tline->type == TOK_WHITESPACE)
  1270.             tline = tline->next;
  1271.         if (!tline) {
  1272.             error (ERR_NONFATAL|ERR_OFFBY1,
  1273.                "parameter identifier expected");
  1274.             return 3;
  1275.         }
  1276.         if (tline->type != TOK_ID) {
  1277.             error (ERR_NONFATAL|ERR_OFFBY1,
  1278.                "`%s': parameter identifier expected",
  1279.                tline->text);
  1280.             return 3;
  1281.         }
  1282.         tline->type = TOK_SMAC_PARAM + nparam++;
  1283.         tline = tline->next;
  1284.         if (tline && tline->type == TOK_WHITESPACE)
  1285.             tline = tline->next;
  1286.         if (tline && tline->type == TOK_OTHER &&
  1287.             !strcmp(tline->text, ",")) {
  1288.             tline = tline->next;
  1289.             continue;
  1290.         }
  1291.         if (!tline || tline->type != TOK_OTHER ||
  1292.             strcmp(tline->text, ")")) {
  1293.             error (ERR_NONFATAL|ERR_OFFBY1,
  1294.                "`)' expected to terminate macro template");
  1295.             return 3;
  1296.         }
  1297.         break;
  1298.         }
  1299.         last = tline;
  1300.         tline = tline->next;
  1301.     }
  1302.     if (tline && tline->type == TOK_WHITESPACE)
  1303.         last = tline, tline = tline->next;
  1304.     macro_start = NULL;
  1305.     last->next = NULL;
  1306.     t = tline;
  1307.     while (t) {
  1308.         if (t->type == TOK_ID) {
  1309.         for (tt = param_start; tt; tt = tt->next)
  1310.             if (tt->type >= TOK_SMAC_PARAM &&
  1311.             !strcmp(tt->text, t->text))
  1312.             t->type = tt->type;
  1313.         }
  1314.         tt = t->next;
  1315.         t->next = macro_start;
  1316.         macro_start = t;
  1317.         t = tt;
  1318.     }
  1319.     /*
  1320.      * Good. We now have a macro name, a parameter count, and a
  1321.      * token list (in reverse order) for an expansion. We ought
  1322.      * to be OK just to create an SMacro, store it, and let
  1323.      * free_tlist have the rest of the line (which we have
  1324.      * carefully re-terminated after chopping off the expansion
  1325.      * from the end).
  1326.      */
  1327.     if (smacro_defined (mname, nparam, &smac)) {
  1328.         if (!smac)
  1329.         error (ERR_WARNING|ERR_OFFBY1,
  1330.                "single-line macro `%s' defined both with and"
  1331.                " without parameters", mname);
  1332.         else {
  1333.         /*
  1334.          * We're redefining, so we have to take over an
  1335.          * existing SMacro structure. This means freeing
  1336.          * what was already in it.
  1337.          */
  1338.         nasm_free (smac->name);
  1339.         free_tlist (smac->expansion);
  1340.         }
  1341.     } else {
  1342.         smac = nasm_malloc(sizeof(SMacro));
  1343.         smac->next = *smhead;
  1344.         *smhead = smac;
  1345.     }
  1346.     smac->name = nasm_strdup(p);
  1347.     smac->casesense = (i == PP_DEFINE);
  1348.     smac->nparam = nparam;
  1349.     smac->expansion = macro_start;
  1350.     smac->in_progress = FALSE;
  1351.     return 3;
  1352.  
  1353.       case PP_LINE:
  1354.     /*
  1355.      * Syntax is `%line nnn[+mmm] [filename]'
  1356.      */
  1357.     tline = tline->next;
  1358.     if (tline && tline->type == TOK_WHITESPACE)
  1359.         tline = tline->next;
  1360.     if (!tline || tline->type != TOK_NUMBER) {
  1361.         error (ERR_NONFATAL|ERR_OFFBY1, "`%%line' expects line number");
  1362.         return 3;
  1363.     }
  1364.     k = readnum(tline->text, &j);
  1365.     m = 1;
  1366.     tline = tline->next;
  1367.     if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "+")) {
  1368.         tline = tline->next;
  1369.         if (!tline || tline->type != TOK_NUMBER) {
  1370.         error (ERR_NONFATAL|ERR_OFFBY1,
  1371.                "`%%line' expects line increment");
  1372.         return 3;
  1373.         }
  1374.         m = readnum(tline->text, &j);
  1375.         tline = tline->next;
  1376.     }
  1377.     if (tline && tline->type == TOK_WHITESPACE)
  1378.         tline = tline->next;
  1379.     istk->lineno = k;
  1380.     istk->lineinc = m;
  1381.     if (tline) {
  1382.         char *s = detoken(tline);
  1383.         nasm_free (istk->fname);
  1384.         istk->fname = s;
  1385.     }
  1386.     return 5;
  1387.  
  1388.       default:
  1389.     error(ERR_FATAL|ERR_OFFBY1,
  1390.           "preprocessor directive `%s' not yet implemented",
  1391.           directives[k]);
  1392.     break;
  1393.     }
  1394.     return 3;
  1395. }
  1396.  
  1397. /*
  1398.  * Expand all single-line macro calls made in the given line.
  1399.  * Return the expanded version of the line. The original is deemed
  1400.  * to be destroyed in the process. (In reality we'll just move
  1401.  * Tokens from input to output a lot of the time, rather than
  1402.  * actually bothering to destroy and replicate.)
  1403.  */
  1404. static Token *expand_smacro (Token *tline) {
  1405.     Token *t, *tt, *mstart, **tail, *thead;
  1406.     SMacro *head, *m;
  1407.     Token **params;
  1408.     int *paramsize;
  1409.     int nparam, sparam, brackets;
  1410.     char *p;
  1411.  
  1412.     tail = &thead;
  1413.     thead = NULL;
  1414.  
  1415.     while (tline) {
  1416.     while (tline && tline->type != TOK_ID &&
  1417.            (tline->type != TOK_PREPROC_ID || tline->text[1] != '$')) {
  1418.         if (tline->type == TOK_SMAC_END) {
  1419.         tline->mac->in_progress = FALSE;
  1420.         t = tline;
  1421.         tline = tline->next;
  1422.         nasm_free (t);
  1423.         } else {
  1424.         t = *tail = tline;
  1425.         tline = tline->next;
  1426.         t->mac = NULL;
  1427.         t->next = NULL;
  1428.         tail = &t->next;
  1429.         if (t->type == TOK_PS_OTHER) {
  1430.             /*
  1431.              * If we see a PS_OTHER, we must at the very
  1432.              * least restore its correct token type. We
  1433.              * should also check for a %$ token, since this
  1434.              * is the point at which we expand context-
  1435.              * local labels.
  1436.              */
  1437.             t->type = TOK_ID;
  1438.             if (t->text[0] == '%' && t->text[1] == '$') {
  1439.             Context *c = get_ctx (t->text);
  1440.             char *p, *q, buffer[40];
  1441.  
  1442.             if (c) {
  1443.                 q = t->text+1;
  1444.                 q += strspn(q, "$");
  1445.                 sprintf(buffer, "..@%lu.", c->number);
  1446.                 p = nasm_malloc (strlen(buffer)+strlen(q)+1);
  1447.                 strcpy (p, buffer);
  1448.                 strcat (p, q);
  1449.                 nasm_free (t->text);
  1450.                 t->text = p;
  1451.             }
  1452.             }
  1453.         }
  1454.         }
  1455.     }
  1456.     if (!tline)
  1457.         break;
  1458.     /*
  1459.      * We've hit an identifier. As in is_mmacro below, we first
  1460.      * check whether the identifier is a single-line macro at
  1461.      * all, then think about checking for parameters if
  1462.      * necessary.
  1463.      */
  1464.     if (tline->type == TOK_ID) {
  1465.         head = smacros[hash(tline->text)];
  1466.         p = tline->text;
  1467.     } else {
  1468.         Context *ctx = get_ctx (tline->text);
  1469.         if (ctx) {
  1470.         p = tline->text+1;
  1471.         p += strspn(p, "$");
  1472.         head = ctx->localmac;
  1473.         } else {
  1474.         tline->type = TOK_OTHER; /* so it will get copied above */
  1475.         continue;        
  1476.         }
  1477.     }
  1478.     for (m = head; m; m = m->next)
  1479.         if (!mstrcmp(m->name, p, m->casesense))
  1480.         break;
  1481.     if (!m || m->in_progress) {
  1482.         /*
  1483.          * Either we didn't find a macro, so this can't be a
  1484.          * macro call, or we found a macro which was already in
  1485.          * progress, in which case we don't _treat_ this as a
  1486.          * macro call. Copy it through and ignore it.
  1487.          */
  1488.         tline->type = TOK_PS_OTHER;   /* so it will get copied above */
  1489.         continue;
  1490.     }
  1491.     mstart = tline;
  1492.     if (m->nparam == 0) {
  1493.         /*
  1494.          * Simple case: the macro is parameterless. Discard the
  1495.          * one token that the macro call took, and push the
  1496.          * expansion back on the to-do stack.
  1497.          */
  1498.         params = NULL;
  1499.         paramsize = NULL;
  1500.     } else {
  1501.         /*
  1502.          * Complicated case: at least one macro with this name
  1503.          * exists and takes parameters. We must find the
  1504.          * parameters in the call, count them, find the SMacro
  1505.          * that corresponds to that form of the macro call, and
  1506.          * substitute for the parameters when we expand. What a
  1507.          * pain.
  1508.          */
  1509.         nparam = sparam = 0;
  1510.         params = NULL;
  1511.         paramsize = NULL;
  1512.         tline = tline->next;
  1513.         if (tline && tline->type == TOK_WHITESPACE)
  1514.         tline = tline->next;
  1515.         if (!tline || tline->type != TOK_OTHER ||
  1516.         strcmp(tline->text, "(")) {
  1517.         /*
  1518.          * This macro wasn't called with parameters: ignore
  1519.          * the call. (Behaviour borrowed from gnu cpp.)
  1520.          */
  1521.         tline = mstart;
  1522.         tline->type = TOK_PS_OTHER;
  1523.         continue;
  1524.         }
  1525.         tline = tline->next;
  1526.         while (1) {
  1527.         if (tline && tline->type == TOK_WHITESPACE)
  1528.             tline = tline->next;
  1529.         if (!tline) {
  1530.             error(ERR_NONFATAL|ERR_OFFBY1,
  1531.               "macro call expects terminating `)'");
  1532.             break;
  1533.         }
  1534.         if (nparam >= sparam) {
  1535.             sparam += PARAM_DELTA;
  1536.             params = nasm_realloc (params, sparam*sizeof(Token *));
  1537.             paramsize = nasm_realloc (paramsize, sparam*sizeof(int));
  1538.         }
  1539.         params[nparam] = tline;
  1540.         paramsize[nparam] = 0;
  1541.         brackets = 0;
  1542.         if (tline && tline->type == TOK_OTHER &&
  1543.             !strcmp(tline->text, "{")) {
  1544.             params[nparam] = tline = tline->next;
  1545.             while (tline && (brackets > 0 ||
  1546.                      tline->type != TOK_OTHER ||
  1547.                      strcmp(tline->text, "}"))) {
  1548.             tline = tline->next;
  1549.             paramsize[nparam]++;
  1550.             }
  1551.             tline = tline->next;
  1552.             if (tline && tline->type == TOK_WHITESPACE)
  1553.             tline = tline->next;
  1554.             if (tline && (tline->type != TOK_OTHER ||
  1555.                   (strcmp(tline->text, ")") &&
  1556.                    strcmp(tline->text, ",")))) {
  1557.             error (ERR_NONFATAL|ERR_OFFBY1, "braces do not "
  1558.                    "enclose all of macro parameter");
  1559.             }
  1560.             if (tline && tline->type == TOK_OTHER &&
  1561.             !strcmp(tline->text, ","))
  1562.             tline = tline->next;
  1563.         } else {
  1564.             while (tline && (brackets > 0 ||
  1565.                      tline->type != TOK_OTHER ||
  1566.                      (strcmp(tline->text, ",") &&
  1567.                       strcmp(tline->text, ")")))) {
  1568.             if (tline->type == TOK_OTHER && !tline->text[1])
  1569.                 brackets += (tline->text[0] == '(' ? 1 :
  1570.                      tline->text[0] == ')' ? -1 : 0);
  1571.             tline = tline->next;
  1572.             paramsize[nparam]++;
  1573.             }
  1574.         }
  1575.         nparam++;
  1576.         if (tline && !strcmp(tline->text, ")"))
  1577.             break;
  1578.         if (tline && !strcmp(tline->text, ","))
  1579.             tline = tline->next;
  1580.         }
  1581.         while (m && m->nparam != nparam) {
  1582.         while ( (m = m->next) )
  1583.             if (!strcmp(m->name, mstart->text))
  1584.             break;
  1585.         }
  1586.         if (!m) {
  1587.         error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
  1588.                "macro `%s' exists, but not taking %d parameters",
  1589.                mstart->text, nparam);
  1590.         nasm_free (params);
  1591.         nasm_free (paramsize);
  1592.         tline = mstart;
  1593.         tline->type = TOK_PS_OTHER;
  1594.         continue;
  1595.         }
  1596.     }
  1597.     /*
  1598.      * Expand the macro: we are placed on the last token of the
  1599.      * call, so that we can easily split the call from the
  1600.      * following tokens. We also start by pushing an SMAC_END
  1601.      * token for the cycle removal.
  1602.      */
  1603.     t = tline;
  1604.     tline = tline->next;
  1605.     t->next = NULL;
  1606.     tt = nasm_malloc(sizeof(Token));
  1607.     tt->type = TOK_SMAC_END;
  1608.     tt->text = NULL;
  1609.     tt->mac = m;
  1610.     m->in_progress = TRUE;
  1611.     tt->next = tline;
  1612.     tline = tt;
  1613.     for (t = m->expansion; t; t = t->next) {
  1614.         if (t->type >= TOK_SMAC_PARAM) {
  1615.         Token *pcopy = tline, **ptail = &pcopy;
  1616.         Token *ttt, *pt;
  1617.         int i;
  1618.         
  1619.         ttt = params[t->type - TOK_SMAC_PARAM];
  1620.         for (i=0; i<paramsize[t->type-TOK_SMAC_PARAM]; i++) {
  1621.             pt = *ptail = nasm_malloc(sizeof(Token));
  1622.             pt->next = tline;
  1623.             ptail = &pt->next;
  1624.             pt->text = nasm_strdup(ttt->text);
  1625.             pt->type = ttt->type;
  1626.             pt->mac = NULL;
  1627.             ttt = ttt->next;
  1628.         }
  1629.         tline = pcopy;
  1630.         } else {
  1631.         tt = nasm_malloc(sizeof(Token));
  1632.         tt->type = t->type;
  1633.         tt->text = nasm_strdup(t->text);
  1634.         tt->mac = NULL;
  1635.         tt->next = tline;
  1636.         tline = tt;
  1637.         }
  1638.     }
  1639.  
  1640.     /*
  1641.      * Having done that, get rid of the macro call, and clean
  1642.      * up the parameters.
  1643.      */
  1644.     nasm_free (params);
  1645.     nasm_free (paramsize);
  1646.     free_tlist (mstart);
  1647.     }
  1648.  
  1649.     return thead;
  1650. }
  1651.  
  1652. /*
  1653.  * Ensure that a macro parameter contains a condition code and
  1654.  * nothing else. Return the condition code index if so, or -1
  1655.  * otherwise.
  1656.  */
  1657. static int find_cc (Token *t) {
  1658.     Token *tt;
  1659.     int i, j, k, m;
  1660.  
  1661.     if (t && t->type == TOK_WHITESPACE)
  1662.     t = t->next;
  1663.     if (t->type != TOK_ID)
  1664.     return -1;
  1665.     tt = t->next;
  1666.     if (tt && tt->type == TOK_WHITESPACE)
  1667.     tt = tt->next;
  1668.     if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
  1669.     return -1;
  1670.  
  1671.     i = -1;
  1672.     j = sizeof(conditions)/sizeof(*conditions);
  1673.     while (j-i > 1) {
  1674.     k = (j+i) / 2;
  1675.     m = nasm_stricmp(t->text, conditions[k]);
  1676.     if (m == 0) {
  1677.         i = k;
  1678.         j = -2;
  1679.         break;
  1680.     } else if (m < 0) {
  1681.         j = k;
  1682.     } else
  1683.         i = k;
  1684.     }
  1685.     if (j != -2)
  1686.     return -1;
  1687.     return i;
  1688. }
  1689.  
  1690. /*
  1691.  * Determine whether the given line constitutes a multi-line macro
  1692.  * call, and return the MMacro structure called if so. Doesn't have
  1693.  * to check for an initial label - that's taken care of in
  1694.  * expand_mmacro - but must check numbers of parameters. Guaranteed
  1695.  * to be called with tline->type == TOK_ID, so the putative macro
  1696.  * name is easy to find.
  1697.  */
  1698. static MMacro *is_mmacro (Token *tline, Token ***params_array) {
  1699.     MMacro *head, *m;
  1700.     Token **params;
  1701.     int nparam;
  1702.  
  1703.     head = mmacros[hash(tline->text)];
  1704.  
  1705.     /*
  1706.      * Efficiency: first we see if any macro exists with the given
  1707.      * name. If not, we can return NULL immediately. _Then_ we
  1708.      * count the parameters, and then we look further along the
  1709.      * list if necessary to find the proper MMacro.
  1710.      */
  1711.     for (m = head; m; m = m->next)
  1712.     if (!mstrcmp(m->name, tline->text, m->casesense))
  1713.         break;
  1714.     if (!m)
  1715.     return NULL;
  1716.  
  1717.     /*
  1718.      * OK, we have a potential macro. Count and demarcate the
  1719.      * parameters.
  1720.      */
  1721.     count_mmac_params (tline->next, &nparam, ¶ms);
  1722.  
  1723.     /*
  1724.      * So we know how many parameters we've got. Find the MMacro
  1725.      * structure that handles this number.
  1726.      */
  1727.     while (m) {
  1728.     if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max)) {
  1729.         /*
  1730.          * This one is right. Just check if cycle removal
  1731.          * prohibits us using it before we actually celebrate...
  1732.          */
  1733.         if (m->in_progress) {
  1734.         error (ERR_NONFATAL|ERR_OFFBY1,
  1735.                "self-reference in multi-line macro `%s'",
  1736.                m->name);
  1737.         nasm_free (params);
  1738.         return NULL;
  1739.         }
  1740.         /*
  1741.          * It's right, and we can use it. Add its default
  1742.          * parameters to the end of our list if necessary.
  1743.          */
  1744.         params = nasm_realloc (params, (m->nparam_max+1)*sizeof(*params));
  1745.         if (m->defaults) {
  1746.         while (nparam < m->nparam_max) {
  1747.             params[nparam] = m->defaults[nparam - m->nparam_min];
  1748.             nparam++;
  1749.         }
  1750.         } else {
  1751.         while (nparam < m->nparam_max) {
  1752.             params[nparam] = NULL;
  1753.             nparam++;
  1754.         }
  1755.         }
  1756.         /*
  1757.          * Then terminate the parameter list, and leave.
  1758.          */
  1759.         params[m->nparam_max] = NULL;
  1760.         *params_array = params;
  1761.         return m;
  1762.     }
  1763.     /*
  1764.      * This one wasn't right: look for the next one with the
  1765.      * same name.
  1766.      */
  1767.     for (m = m->next; m; m = m->next)
  1768.         if (!mstrcmp(m->name, tline->text, m->casesense))
  1769.         break;
  1770.     }
  1771.  
  1772.     /*
  1773.      * After all that, we didn't find one with the right number of
  1774.      * parameters. Issue a warning, and fail to expand the macro.
  1775.      */
  1776.     error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
  1777.        "macro `%s' exists, but not taking %d parameters",
  1778.        tline->text, nparam);
  1779.     nasm_free (params);
  1780.     return NULL;
  1781. }
  1782.  
  1783. /*
  1784.  * Expand the multi-line macro call made by the given line, if
  1785.  * there is one to be expanded. If there is, push the expansion on
  1786.  * istk->expansion and return 1 or 2, as according to whether a
  1787.  * line sync is needed (2 if it is). Otherwise return 0.
  1788.  */
  1789. static int expand_mmacro (Token *tline) {
  1790.     Token *label = NULL, **params, *t, *tt, *ttt, *last = NULL;
  1791.     MMacro *m = NULL;
  1792.     Line *l, *ll;
  1793.     int i, n, nparam, *paramlen;
  1794.     int need_sync = FALSE;
  1795.  
  1796.     t = tline;
  1797.     if (t && t->type == TOK_WHITESPACE)
  1798.     t = t->next;
  1799.     if (t && t->type == TOK_ID) {
  1800.     m = is_mmacro (t, ¶ms);
  1801.     if (!m) {
  1802.         /*
  1803.          * We have an id which isn't a macro call. We'll assume
  1804.          * it might be a label; we'll also check to see if a
  1805.          * colon follows it. Then, if there's another id after
  1806.          * that lot, we'll check it again for macro-hood.
  1807.          */
  1808.         last = t, t = t->next;
  1809.         if (t && t->type == TOK_WHITESPACE)
  1810.         last = t, t = t->next;
  1811.         if (t && t->type == TOK_OTHER && !strcmp(t->text, ":"))
  1812.         last = t, t = t->next;
  1813.         if (t && t->type == TOK_WHITESPACE)
  1814.         last = t, t = t->next;
  1815.         if (t && t->type == TOK_ID) {
  1816.         m = is_mmacro(t, ¶ms);
  1817.         if (m) {
  1818.             last->next = NULL;
  1819.             label = tline;
  1820.             tline = t;
  1821.         }
  1822.         }
  1823.     }    
  1824.     }
  1825.     if (!m)
  1826.     return 0;
  1827.  
  1828.     /*
  1829.      * If we're not already inside another macro expansion, we'd
  1830.      * better push a line synchronisation to ensure we stay put on
  1831.      * line numbering.
  1832.      */
  1833.     if (!istk->expansion)
  1834.     need_sync = TRUE;
  1835.  
  1836.     /*
  1837.      * Fix up the parameters: this involves stripping leading and
  1838.      * trailing whitespace, then stripping braces if they are
  1839.      * present.
  1840.      */
  1841.     for (nparam = 0; params[nparam]; nparam++);
  1842.     paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL;
  1843.  
  1844.     for (i = 0; params[i]; i++) {
  1845.     int brace = FALSE;
  1846.     int comma = (!m->plus || i < nparam-1);
  1847.  
  1848.     t = params[i];
  1849.     if (t && t->type == TOK_WHITESPACE)
  1850.         t = t->next;
  1851.     if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
  1852.         t = t->next, brace = TRUE, comma = FALSE;
  1853.     params[i] = t;
  1854.     paramlen[i] = 0;
  1855.     while (t) {
  1856.         if (!t)               /* end of param because EOL */
  1857.         break;
  1858.         if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
  1859.         break;               /* ... because we have hit a comma */
  1860.         if (comma && t->type == TOK_WHITESPACE &&
  1861.         t->next->type == TOK_OTHER && !strcmp(t->next->text, ","))
  1862.         break;               /* ... or a space then a comma */
  1863.         if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
  1864.         break;               /* ... or a brace */
  1865.         t = t->next;
  1866.         paramlen[i]++;
  1867.     }
  1868.     }
  1869.  
  1870.     /*
  1871.      * OK, we have a MMacro structure together with a set of
  1872.      * parameters. We must now go through the expansion and push
  1873.      * _copies_ of each Line on to istk->expansion, having first
  1874.      * substituted for most % tokens (%1, %+1, %-1, %%foo). Note
  1875.      * that %$bar, %$$baz, %$$$quux, and so on, do not get
  1876.      * substituted here but rather have to wait until the
  1877.      * single-line macro substitution process. This is because they
  1878.      * don't just crop up in macro definitions, but can appear
  1879.      * anywhere they like.
  1880.      *
  1881.      * First, push an end marker on to istk->expansion, and mark
  1882.      * this macro as in progress.
  1883.      */
  1884.     ll = nasm_malloc(sizeof(Line));
  1885.     ll->next = istk->expansion;
  1886.     ll->finishes = m;
  1887.     ll->first = NULL;
  1888.     istk->expansion = ll;
  1889.     m->in_progress = TRUE;
  1890.     for (l = m->expansion; l; l = l->next) {
  1891.     Token **tail;
  1892.  
  1893.     ll = nasm_malloc(sizeof(Line));
  1894.     ll->next = istk->expansion;
  1895.     ll->finishes = NULL;
  1896.     ll->first = NULL;
  1897.     tail = &ll->first;
  1898.  
  1899.     for (t = l->first; t; t = t->next) {
  1900.         char *text;
  1901.         int type = 0, cc;           /* type = 0 to placate optimisers */
  1902.         char tmpbuf[30];
  1903.  
  1904.         if (t->type == TOK_PREPROC_ID &&
  1905.         (t->text[1] == '+' || t->text[1] == '-' ||
  1906.          t->text[1] == '%' ||
  1907.          (t->text[1] >= '0' && t->text[1] <= '9'))) {
  1908.         /*
  1909.          * We have to make a substitution of one of the
  1910.          * forms %1, %-1, %+1, %%foo.
  1911.          */
  1912.         switch (t->text[1]) {
  1913.           case '%':
  1914.             type = TOK_ID;
  1915.             sprintf(tmpbuf, "..@%lu.", unique);
  1916.             text = nasm_malloc(strlen(tmpbuf)+strlen(t->text+2)+1);
  1917.             strcpy(text, tmpbuf);
  1918.             strcat(text, t->text+2);
  1919.             break;
  1920.           case '-':
  1921.             n = atoi(t->text+2)-1;
  1922.             tt = params[n];
  1923.             cc = find_cc (tt);
  1924.             if (cc == -1) {
  1925.             error (ERR_NONFATAL|ERR_OFFBY1,
  1926.                    "macro parameter %d is not a condition code",
  1927.                    n+1);
  1928.             text = NULL;
  1929.             } else {
  1930.             type = TOK_ID;
  1931.             if (inverse_ccs[cc] == -1) {
  1932.                 error (ERR_NONFATAL|ERR_OFFBY1,
  1933.                    "condition code `%s' is not invertible",
  1934.                    conditions[cc]);
  1935.                 text = NULL;
  1936.             } else
  1937.                 text = nasm_strdup(conditions[inverse_ccs[cc]]);
  1938.             }
  1939.             break;
  1940.           case '+':
  1941.             n = atoi(t->text+2)-1;
  1942.             tt = params[n];
  1943.             cc = find_cc (tt);
  1944.             if (cc == -1) {
  1945.             error (ERR_NONFATAL|ERR_OFFBY1,
  1946.                    "macro parameter %d is not a condition code",
  1947.                    n+1);
  1948.             text = NULL;
  1949.             } else {
  1950.             type = TOK_ID;
  1951.             text = nasm_strdup(conditions[cc]);
  1952.             }
  1953.             break;
  1954.           default:
  1955.             n = atoi(t->text+1)-1;
  1956.             if (n < nparam) {
  1957.             ttt = params[n];
  1958.             for (i=0; i<paramlen[n]; i++) {
  1959.                 tt = *tail = nasm_malloc(sizeof(Token));
  1960.                 tt->next = NULL;
  1961.                 tail = &tt->next;
  1962.                 tt->type = ttt->type;
  1963.                 tt->text = nasm_strdup(ttt->text);
  1964.                 tt->mac = NULL;
  1965.                 ttt = ttt->next;
  1966.             }
  1967.             }
  1968.             text = NULL;       /* we've done it here */
  1969.             break;
  1970.         }
  1971.         } else {
  1972.         type = t->type;
  1973.         text = nasm_strdup(t->text);
  1974.         }
  1975.  
  1976.         if (text) {
  1977.         tt = *tail = nasm_malloc(sizeof(Token));
  1978.         tt->next = NULL;
  1979.         tail = &tt->next;
  1980.         tt->type = type;
  1981.         tt->text = text;
  1982.         tt->mac = NULL;
  1983.         }
  1984.     }
  1985.  
  1986.     istk->expansion = ll;
  1987.  
  1988.     }
  1989.  
  1990.     /*
  1991.      * If we had a label, push it on the front of the first line of
  1992.      * the macro expansion.
  1993.      */
  1994.     if (label) {
  1995.     last->next = istk->expansion->first;
  1996.     istk->expansion->first = label;
  1997.     }
  1998.  
  1999.     /*
  2000.      * Clean up.
  2001.      */
  2002.     unique++;
  2003.     nasm_free (paramlen);
  2004.     nasm_free (params);
  2005.     free_tlist (tline);
  2006.  
  2007.     list->uplevel (m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
  2008.  
  2009.     return need_sync ? 2 : 1;
  2010. }
  2011.  
  2012. static void pp_reset (char *file, efunc errfunc, ListGen *listgen) {
  2013.     int h;
  2014.  
  2015.     error = errfunc;
  2016.     cstk = NULL;
  2017.     linesync = outline = NULL;
  2018.     istk = nasm_malloc(sizeof(Include));
  2019.     istk->next = NULL;
  2020.     istk->conds = NULL;
  2021.     istk->expansion = NULL;
  2022.     istk->fp = fopen(file, "r");
  2023.     istk->fname = nasm_strdup(file);
  2024.     istk->lineno = istk->lineinc = 1;
  2025.     if (!istk->fp)
  2026.     error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file);
  2027.     defining = NULL;
  2028.     for (h=0; h<NHASH; h++) {
  2029.     mmacros[h] = NULL;
  2030.     smacros[h] = NULL;
  2031.     }
  2032.     unique = 0;
  2033.     stdmacpos = stdmac;
  2034.     list = listgen;
  2035. }
  2036.  
  2037. static char *pp_getline (void) {
  2038.     char *line;
  2039.     Token *tline;
  2040.     int ret;
  2041.  
  2042.     if (outline) {
  2043.     line = outline;
  2044.     outline = NULL;
  2045.     return line;
  2046.     }
  2047.  
  2048.     while (1) {
  2049.     /*
  2050.      * Fetch a tokenised line, either from the macro-expansion
  2051.      * buffer or from the input file.
  2052.      */
  2053.     tline = NULL;
  2054.     while (istk->expansion && istk->expansion->finishes) {
  2055.         Line *l = istk->expansion;
  2056.         l->finishes->in_progress = FALSE;
  2057.         istk->expansion = l->next;
  2058.         nasm_free (l);
  2059.         list->downlevel (LIST_MACRO);
  2060.         if (!istk->expansion)
  2061.         line_sync();
  2062.     }
  2063.     if (istk->expansion) {
  2064.         char *p;
  2065.         Line *l = istk->expansion;
  2066.         tline = l->first;
  2067.         istk->expansion = l->next;
  2068.         nasm_free (l);
  2069.         p = detoken(tline);
  2070.         list->line (LIST_MACRO, p);
  2071.         nasm_free(p);
  2072.         if (!istk->expansion)
  2073.         line_sync();
  2074.     } else {
  2075.         line = read_line();
  2076.         while (!line) {
  2077.         /*
  2078.          * The current file has ended; work down the istk
  2079.          * until we find a file we can read from.
  2080.          */
  2081.         Include *i;
  2082.         fclose(istk->fp);
  2083.         if (istk->conds)
  2084.             error(ERR_FATAL, "expected `%%endif' before end of file");
  2085.         i = istk;
  2086.         istk = istk->next;
  2087.         list->downlevel (LIST_INCLUDE);
  2088.         nasm_free (i->fname);
  2089.         nasm_free (i);
  2090.         if (!istk)
  2091.             return NULL;
  2092.         else
  2093.             line_sync();
  2094.         line = read_line();
  2095.         }
  2096.         line = prepreproc(line);
  2097.         tline = tokenise(line);
  2098.         nasm_free (line);
  2099.     }
  2100.  
  2101.     /*
  2102.      * Check the line to see if it's a preprocessor directive.
  2103.      */
  2104.     ret = do_directive(tline);
  2105.     if (ret & 1) {
  2106.         free_tlist (tline);
  2107.         if (ret & 4)
  2108.         line_sync();
  2109.         if ((ret & 2) && !stdmacpos) {/* give a blank line to the output */
  2110.         outline = nasm_strdup("");
  2111.         break;
  2112.         }
  2113.         else
  2114.         continue;
  2115.     } else if (defining) {
  2116.         /*
  2117.          * We're defining a multi-line macro. We emit nothing
  2118.          * at all, not even a blank line (when we finish
  2119.          * defining the macro, we'll emit a line-number
  2120.          * directive so that we keep sync properly), and just
  2121.          * shove the tokenised line on to the macro definition.
  2122.          */
  2123.         Line *l = nasm_malloc(sizeof(Line));
  2124.         l->next = defining->expansion;
  2125.         l->first = tline;
  2126.         l->finishes = FALSE;
  2127.         defining->expansion = l;
  2128.         continue;
  2129.     } else if (istk->conds && !emitting(istk->conds->state)) {
  2130.         /*
  2131.          * We're in a non-emitting branch of a condition block.
  2132.          * Emit nothing at all, not even a blank line: when we
  2133.          * emerge from the condition we'll give a line-number
  2134.          * directive so we keep our place correctly.
  2135.          */
  2136.         free_tlist(tline);
  2137.         continue;
  2138.     } else {
  2139.         tline = expand_smacro(tline);
  2140.         ret = expand_mmacro(tline);
  2141.         if (!ret) {
  2142.         /*
  2143.          * De-tokenise the line again, and emit it.
  2144.          */
  2145.         line = detoken(tline);
  2146.         free_tlist (tline);
  2147.         outline = line;
  2148.         break;
  2149.         } else {
  2150.         if (ret == 2)
  2151.             line_sync();
  2152.         continue;           /* expand_mmacro calls free_tlist */
  2153.         }
  2154.     }
  2155.     }
  2156.  
  2157.     /*
  2158.      * Once we're out of this loop, outline _must_ be non-NULL. The
  2159.      * only question is whether linesync is NULL or not.
  2160.      */
  2161.     if (linesync) {
  2162.     line = linesync;
  2163.     linesync = NULL;
  2164.     } else {
  2165.     line = outline;
  2166.     outline = NULL;
  2167.     }
  2168.     return line;
  2169. }
  2170.  
  2171. static void pp_cleanup (void) {
  2172.     int h;
  2173.  
  2174.     if (defining) {
  2175.     error (ERR_NONFATAL, "end of file while still defining macro `%s'",
  2176.            defining->name);
  2177.     nasm_free (defining->name);
  2178.     free_tlist (defining->dlist);
  2179.     free_llist (defining->expansion);
  2180.     nasm_free (defining);
  2181.     }
  2182.     nasm_free (linesync);           /* might just be necessary */
  2183.     nasm_free (outline);           /* really shouldn't be necessary */
  2184.     while (cstk)
  2185.     ctx_pop();
  2186.     for (h=0; h<NHASH; h++) {
  2187.     while (mmacros[h]) {
  2188.         MMacro *m = mmacros[h];
  2189.         mmacros[h] = mmacros[h]->next;
  2190.         nasm_free (m->name);
  2191.         free_tlist (m->dlist);
  2192.         free_llist (m->expansion);
  2193.         nasm_free (m);
  2194.     }
  2195.     while (smacros[h]) {
  2196.         SMacro *s = smacros[h];
  2197.         smacros[h] = smacros[h]->next;
  2198.         nasm_free (s->name);
  2199.         free_tlist (s->expansion);
  2200.         nasm_free (s);
  2201.     }
  2202.     }
  2203.     while (istk) {
  2204.     Include *i = istk;
  2205.     istk = istk->next;
  2206.     fclose(i->fp);
  2207.     nasm_free (i->fname);
  2208.     nasm_free (i);
  2209.     }
  2210.     while (cstk)
  2211.     ctx_pop();
  2212. }
  2213.  
  2214. void pp_include_path (char *path) {
  2215.     IncPath *i;
  2216.  
  2217.     i = nasm_malloc(sizeof(IncPath));
  2218.     i->path = nasm_strdup(path);
  2219.     i->next = ipath;
  2220.  
  2221.     ipath = i;
  2222. }
  2223.  
  2224. void pp_pre_include (char *fname) {
  2225.     Token *inc, *space, *name;
  2226.     Line *l;
  2227.  
  2228.     inc = nasm_malloc(sizeof(Token));
  2229.     inc->next = space = nasm_malloc(sizeof(Token));
  2230.     space->next = name = nasm_malloc(sizeof(Token));
  2231.     name->next = NULL;
  2232.  
  2233.     inc->type = TOK_PREPROC_ID;
  2234.     inc->text = nasm_strdup("%include");
  2235.     space->type = TOK_WHITESPACE;
  2236.     space->text = nasm_strdup(" ");
  2237.     name->type = TOK_INTERNAL_STRING;
  2238.     name->text = nasm_strdup(fname);
  2239.  
  2240.     inc->mac = space->mac = name->mac = NULL;
  2241.  
  2242.     l = nasm_malloc(sizeof(Line));
  2243.     l->next = predef;
  2244.     l->first = inc;
  2245.     l->finishes = FALSE;
  2246.     predef = l;
  2247. }
  2248.  
  2249. void pp_pre_define (char *definition) {
  2250.     Token *def, *space, *name;
  2251.     Line *l;
  2252.     char *equals;
  2253.  
  2254.     equals = strchr(definition, '=');
  2255.  
  2256.     def = nasm_malloc(sizeof(Token));
  2257.     def->next = space = nasm_malloc(sizeof(Token));
  2258.     if (equals)
  2259.     *equals = ' ';
  2260.     space->next = name = tokenise(definition);
  2261.     if (equals)
  2262.     *equals = '=';
  2263.  
  2264.     def->type = TOK_PREPROC_ID;
  2265.     def->text = nasm_strdup("%define");
  2266.     space->type = TOK_WHITESPACE;
  2267.     space->text = nasm_strdup(" ");
  2268.  
  2269.     def->mac = space->mac = NULL;
  2270.  
  2271.     l = nasm_malloc(sizeof(Line));
  2272.     l->next = predef;
  2273.     l->first = def;
  2274.     l->finishes = FALSE;
  2275.     predef = l;
  2276. }
  2277.  
  2278. Preproc nasmpp = {
  2279.     pp_reset,
  2280.     pp_getline,
  2281.     pp_cleanup
  2282. };
  2283.